package
{
	import com.pickgliss.events.LoaderEvent;
	import com.pickgliss.loaders.BitmapLoader;
	import com.pickgliss.loaders.ILoader;
	import com.pickgliss.loaders.LoaderManager;
	import com.pickgliss.loaders.PngxLoader;
	import com.pickgliss.loaders.QueueLoader;
	import com.pickgliss.loaders.TextLoader;
	import com.pickgliss.utils.DisplayUtils;
	import com.pickgliss.utils.PNGXEncoder;
	import com.pickgliss.utils.StringUtils;
	
	import flash.display.Bitmap;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.geom.Rectangle;
	import flash.utils.ByteArray;
	
	import mx.collections.ArrayCollection;

	public class ActionModel extends EventDispatcher
	{
		public function ActionModel()
		{
		}
		[Bindable]
		public var actions:ArrayCollection = new ArrayCollection();
		
		private var _notSameFrames:Vector.<PlistFrameInfo>;
		private var _pngxLoader:PngxLoader;
		private var _pngUrl:String = "";
		private var _dataUrl:String = "";
		
		private var _loader:QueueLoader;
		private var _xmlData:XML;
		[Bindable]
		public var bitmap:Bitmap;
		
		public var actionName:String;
		public var actionType:int;
		
		public var registerX:Number = 0;
		public var registerY:Number = 0;
		
		public static const ADD_ACTION:String = "addAction";
		
		[Bindable]
		public var currentAction:ArrayCollection = new ArrayCollection();
		
		[Bindable]
		public var frameList:ArrayCollection;
		[Bindable]
		public function set source(url:String):void
		{
			var ext:String = StringUtils.getFileExtendtionFromUrl(url);
			var filename:String = StringUtils.getFileNameFromUrl(url);
			if(ext == "png")
			{
				_pngUrl = url;
				_dataUrl = StringUtils.fixSameDirUrl(url,filename+".plist");
			}else if(ext == "plist")
			{
				_dataUrl = url;
				_pngUrl = StringUtils.fixSameDirUrl(url,filename+".png");
			}
			
			_loader  = new QueueLoader();
			_pngxLoader = new PngxLoader(_pngUrl,onBitmapComplete);
			_loader.addLoader(_pngxLoader);
			_loader.addLoader(new TextLoader(_dataUrl,onDataComplete));
			_loader.start();
		}
		
		public function get source():String
		{
			return _dataUrl;
		}
		
		
		public function addFrameToCurrentAction(selected:Vector.<Object>):void
		{
			var reversed:Vector.<Object> = selected.reverse();
			for(var i:int = 0;i<reversed.length;i++)
			{
				currentAction.addItem(reversed[i]);
			}
		}
		
		public function removeFrameFromCurrentAction(selected:Vector.<Object>):void
		{
			for(var i:int = 0;i<selected.length;i++)
			{
				removeIndexByName(selected[i]["name"]);
			}
		}
		
		private function removeIndexByName(name:String):int
		{
			for(var i:int = 0;i<currentAction.length;i++)
			{
				var item:Object = currentAction.getItemAt(i);
				if(item["name"] == name){
					currentAction.removeItemAt(i);
					break;
				}
			}
			return -1;
		}
		
		private function onBitmapComplete(loader:ILoader):void
		{
			bitmap = loader.content;
		}
		
		private function onDataComplete(loader:ILoader):void
		{
			_xmlData = new XML(loader.content);
			paresXML();
		}
		
		private static var _instance:ActionModel
		public static function get Instance():ActionModel
		{
			if(_instance == null)
			{
				_instance = new ActionModel();
			}
			return _instance;
		}
		
		public function addCurrentAction():void
		{
			var action:ActionInfo = new ActionInfo();
			action.name = actionName;
			action.type = actionType;
			action.frames = new Vector.<int>();
			for(var i:int = 0;i<currentAction.length;i++)
			{
				for(var j:int = 0;j<_notSameFrames.length;j++)
				{
					if(_notSameFrames[j].equals(PlistFrameInfo(currentAction.getItemAt(i))))
					{
						action.frames.push(j);
					}
				}
			}
			actions.addItem(action);
			dispatchEvent(new Event(ADD_ACTION));
		}
		
		
		public function genrateCurrentBytes():ByteArray
		{
			var iendBytes:ByteArray = new ByteArray();
			iendBytes.writeUnsignedInt(_notSameFrames.length);
			for(var i:int = 0;i<_notSameFrames.length;i++)
			{
				//registerPoint
				iendBytes.writeInt(ActionModel.Instance.registerX + _notSameFrames[i].sourceRect.x);
				iendBytes.writeInt(ActionModel.Instance.registerY + _notSameFrames[i].sourceRect.y);
				//frameRect
				iendBytes.writeInt(_notSameFrames[i].frameRect.x);
				iendBytes.writeInt(_notSameFrames[i].frameRect.y);
				iendBytes.writeInt(_notSameFrames[i].frameRect.width);
				iendBytes.writeInt(_notSameFrames[i].frameRect.height);
			}
			iendBytes.writeUnsignedInt(actions.length)
			for(var j:int = 0;j<actions.length;j++)
			{
				var action:ActionInfo = actions[j];
				iendBytes.writeUTF(action.name);
				iendBytes.writeInt(action.type);
				iendBytes.writeInt(action.frames.length);
				for(var k:int = 0;k<action.frames.length;k++)
				{
					iendBytes.writeInt(action.frames[k]);
				}
			}
			var retult:ByteArray = PNGXEncoder.encode(bitmap.bitmapData,iendBytes);
			return retult;
		}
		
		
		private function generateSameFrames():void
		{
			_notSameFrames = new Vector.<PlistFrameInfo>();
			for(var i:int = 0;i<frameList.length;i++)
			{
				var item:PlistFrameInfo = frameList.getItemAt(i) as PlistFrameInfo;
				var isEqual:Boolean = false;
				for(var j:int = 0;j<_notSameFrames.length;j++)
				{
					if(item.equals(_notSameFrames[j]))isEqual=true;
				}
				if(!isEqual)_notSameFrames.push(item);
			}
		}
		
		private function paresXML():void
		{
			frameList = new ArrayCollection();
			_notSameFrames = new Vector.<PlistFrameInfo>();
			var frameData:XMLList = _xmlData.dict.dict[0].children();
			for(var i:int = 0;i<frameData.length()/2;i++)
			{
				var frameInfo:PlistFrameInfo = new PlistFrameInfo();
				frameInfo.name = frameData[i*2].toString();
				frameList.addItem(frameInfo);
				var frame:XMLList = frameData[i*2+1].children();
				for(var j:int = 0;j<frame.length()/2;j++)
				{
					var key:String = frame[j*2].toString();
					var data:String = frame[j*2+1].toString();
					if(key == "frame")
					{
						frameInfo.frameRect = PlistFrameInfo.processRect(data);
					}else if(key == "sourceColorRect")
					{
						frameInfo.sourceRect = PlistFrameInfo.processRect(data);
					}
				}
			}
			generateSameFrames();
		}
	}
}